using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Text;
using System.Linq;
using Newtonsoft.Json;
using T.FAS.Runtime.Expression.SPI;
using Newtonsoft.Json.Linq;
using System.Net;
using System.IO;
using System.Configuration;
using T.ServiceComponent.Config.Client;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Expression.Entity;

namespace T.FAS.Runtime.Expression.Plugin
{
    public class SGExecutor : DynamicObject, IDynamicActionAdapter
    {
        /// <summary>
        /// JS脚本动态调用Dynamic必备函数
        /// 脚本写法：ConfigCenter.();
        /// </summary>
        /// <param name = "name">动态调用DynamicObject中的函数名称</param>
        /// <param name = "args">参数信息，参数类型必须增加 params</param>
        /// <returns></returns>
        public dynamic DynamicInvoke(string name, params object[] args)
        {
            return ExecuteInvoke(name, args);
        }

        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out dynamic result)
        {
            result = DynamicInvoke(binder.Name, args);
            return true;
        }

        /// <summary>
        /// 执行获取配置中心值的逻辑
        /// </summary>
        /// <param name = "funcName"></param>
        /// <param name = "paramList"></param>
        /// <returns></returns>
        private dynamic ExecuteInvoke(string funcName, object[] paramList)
        {
            throw new FasException(ExprExceptionCode.NotSupported, "Unsupported SG." + funcName);
        }

        /// <summary>
        /// 向指定的SG站点发起Post调用，超时时间默认10分钟
        /// </summary>
        /// <param name = "dataCenterId"></param>
        /// <param name = "serviceId"></param>
        /// <param name = "parameter"></param>
        /// <param name = "timeoutMinitues"></param>
        /// <returns></returns>
        public object Invoke(string serviceId, string parameter)
        {
            Dictionary<string, object> param = JsonConvert.DeserializeObject<Dictionary<string, object>>(parameter);
            if (param == null)
            {
                param = new Dictionary<string, object>();
            }

            ServicePointManager.DefaultConnectionLimit = 2048;
            var domain = GetDataCenterDomain();
            string result = null;
            var request = (HttpWebRequest)WebRequest.Create(domain + "/api/invoke?SID=" + serviceId);
            request.Timeout = 10 * 600 * 1000; //默认超时时间10分钟
            request.Headers.Add("SGC-SData", T.ServiceComponent.Session.Service.AppContext.Current.SessionID);
            var parameterJson = JsonConvert.SerializeObject(param);
            request.Method = "POST";
            request.ContentType = "application/json";
            using (var streamWriter = new StreamWriter(request.GetRequestStream()))
            {
                streamWriter.Write(parameterJson);
                streamWriter.Flush();
                streamWriter.Close();
            }

            using (var httpResponse = (HttpWebResponse)request.GetResponse())
            {
                using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                {
                    result = streamReader.ReadToEnd();
                    httpResponse.Close();
                }
            }

            return ConvertTResponseToTResult(result);
        }

        const string DDPDomainUrl = "FAS.Action.SGQueryDomain";
        /// <summary>
        /// 获取SG站点地址
        /// </summary>
        /// <returns></returns>
        private string GetDataCenterDomain()
        {
            var domain = "";
            try
            {
                domain = ConfigManager.GetConfigValue(DDPDomainUrl);
            }
            catch
            {
                domain = ConfigurationManager.AppSettings.Get(DDPDomainUrl);
            }

            if (string.IsNullOrWhiteSpace(domain))
            {
                domain = ConfigurationManager.AppSettings.Get(DDPDomainUrl);
                if (string.IsNullOrWhiteSpace(domain))
                    domain = "sgi.t.org:9080";
            }

            return "http://" + domain;
        }

        public object ConvertTResponseToTResult(string result)
        {
            var resultdata = JsonConvert.DeserializeObject<JObject>(result);
            if (resultdata != null)
            {
                return resultdata;
            }
            else
            {
                var jarry = JsonConvert.DeserializeObject<JObject>(result);
                if (jarry != null)
                {
                    return jarry;
                }

                throw new FasException(ExprExceptionCode.ErrorExpr, $"{T.ServiceComponent.I18N.Service.TermService.Current.GetText("T_FAS_fasr_Expression_1742467279", "SG服务返回数据结构异常")}");
            }
        }
    }
}